package com.campus.service.Impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.campus.constant.AIChatConstant;
import com.campus.entity.ChatRecords;
import com.campus.mapper.AIMapper;
import com.campus.properties.AIProperties;
import com.campus.result.Result;
import com.campus.service.AIService;
import com.campus.utils.HttpClientUtil;
import com.campus.vo.ChatRecordsVO;
import jakarta.websocket.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
@Slf4j
public class AIServiceImpl implements AIService {

    @Autowired
    private AIProperties aiProperties;

    @Autowired
    private AIMapper aiMapper;
    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    /**
     * 调用 AI 模型并返回结果
     * @param message
     * @param session
     */
    @Override
    public void chatWithCloseAI(String message, Session session) {
        // message 转JSON 提取信息
        JSONObject jsonObject = JSONObject.parseObject(message);
        String userMessage = jsonObject.getString("userMessage");
        String model = jsonObject.getString("model");

        log.info("接收到来自客户端的消息：{}", userMessage);

        executor.submit(() -> {
            try {
                sendAIRequest(session, model, userMessage);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 调用 AI 模型并返回结果
     * @param session
     * @param model
     * @param userMessage
     * @throws IOException
     */
    private void sendAIRequest(Session session, String model, String userMessage) throws IOException {
        String apiKey = aiProperties.getCloseAI().getApiKey(); // 获取 API Key
        String url = aiProperties.getCloseAI().getBaseUrl() + AIChatConstant.Path.CHAT_COMPLETIONS; // 获取 API 请求 URL

        // 请求头
        Map<String, String> headers = Map.of(
                AIChatConstant.Header.AUTHORIZATION_HEADER, AIChatConstant.Header.BEARER + apiKey,
                AIChatConstant.Header.CONTENT_TYPE, AIChatConstant.Header.JSON_CONTENT_TYPE
        );

        // 请求体
        Map<String, Object> requestBody = Map.of(
                "model", model,
                "messages", List.of(
                        Map.of("role", "system", "content", AIChatConstant.Chat.CHAT_ASSISTANT_HINT),
                        Map.of("role", "user", "content", userMessage)
                ),
                "stream", true
        );

        try (
            InputStream responseStream = HttpClientUtil.doPost4JsonStream(url, Map.of("json", JSONObject.toJSONString(requestBody)), headers);
            BufferedReader reader = new BufferedReader(new InputStreamReader(responseStream))
        ) {
            String line;
            while ((line = reader.readLine()) != null && session.isOpen()) {
                if (!line.trim().isEmpty()) {
                    String jsonResponseStr = line.substring(line.indexOf("{"), line.lastIndexOf("}") + 1);
                    JSONObject jsonResponse = JSONObject.parseObject(jsonResponseStr);
                    JSONArray choices = jsonResponse.getJSONArray("choices");

                    if (choices != null && !choices.isEmpty()) {
                        JSONObject choice = choices.getJSONObject(0);
                        String finishReason = choice.getString("finish_reason");
                        // 向客户端返回 AI 回答
                        session.getBasicRemote().sendText(jsonResponseStr);
                        if ("stop".equals(finishReason)) {
                            // openai 的流式数据返回中，出现 finish_reason 为 stop 时代表回复结束
                            break;
                        }
                    }
                }
            }
        } catch (IOException e) {
            session.getBasicRemote().sendText(String.valueOf(Result.error("API 调用失败")));
        }
    }

    /**
     * 根据传入的聊天记录生成标题再插入数据库并将记录返回
     * @param message
     * @param userId
     * @return
     */
    @Override
    public ChatRecordsVO.item makeChatTitle(String message, Long userId) {

        // 调用 AI 获取聊天标题
        String title = getTitle(message);
        log.info("AI 获取的标题：{}", title);

        // 构造插入数据库的数据
        ChatRecords chatRecords = ChatRecords.builder()
                .userId(userId)
                .content(message)
                .title(title)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();

        // 插入数据库 这里的插入操作会自动获取到自增的 id
        aiMapper.insert(chatRecords);

        // 构造返回数据
        ChatRecordsVO.item recordsVO = new ChatRecordsVO.item();
        BeanUtils.copyProperties(chatRecords, recordsVO);

        return recordsVO;
    }

    /**
     * 调取 AI 获取对话标题
     * @param message
     * @return
     */
    private String getTitle(String message) {
        String apiKey = aiProperties.getCloseAI().getApiKey();
        String url = aiProperties.getCloseAI().getBaseUrl() + AIChatConstant.Path.CHAT_COMPLETIONS;

        Map<String, String> headers = Map.of(
                AIChatConstant.Header.AUTHORIZATION_HEADER, AIChatConstant.Header.BEARER + apiKey,
                AIChatConstant.Header.CONTENT_TYPE, AIChatConstant.Header.JSON_CONTENT_TYPE
        );

        Map<String, Object> requestBody = Map.of(
                "model", AIChatConstant.Model.GPT_3_5_TURBO,
                "messages", List.of(
                        Map.of("role", "system", "content", AIChatConstant.Chat.TITLE_ASSISTANT_HINT),
                        Map.of("role", "user", "content", message)
                )
        );

        // 发送请求
        try {
            String requestBodyJson = JSONObject.toJSONString(requestBody);
            // 发起POST请求，获取完整JSON响应
            String responseJson = HttpClientUtil.doPost4Json(url, Map.of("json", requestBodyJson), headers);

            // 解析完整JSON响应
            JSONObject jsonResponse = JSONObject.parseObject(responseJson);
            JSONArray choices = jsonResponse.getJSONArray("choices");
            if (choices != null && !choices.isEmpty()) {
                JSONObject choice = choices.getJSONObject(0);
                return choice.getJSONObject("message").getString("content");
            }
        } catch (IOException e) {
            System.out.println("OpenAI API 调用失败: " + e.getMessage());
        }
        return null;
    }


    /**
     * 获取某个用户的全部聊天记录
     * @param userId
     * @return
     */
    @Override
    public List<ChatRecordsVO> queryChatRecordsByUserId(Long userId) {
        // 查询数据库
        List<ChatRecords> records = aiMapper.selectByUserId(userId);

        // 获取当前的时间
        LocalDateTime now = LocalDateTime.now();

        // 按时间进行分类处理
        List<ChatRecordsVO.item> todayRecords = new ArrayList<>();
        List<ChatRecordsVO.item> yesterdayRecords = new ArrayList<>();
        List<ChatRecordsVO.item> last7DaysRecords = new ArrayList<>();
        List<ChatRecordsVO.item> lastMonthRecords = new ArrayList<>();
        Map<String, List<ChatRecordsVO.item>> olderRecords = new TreeMap<>(); // 按月份或年份+月份存储

        // 遍历分类
        for (ChatRecords record : records) {
            LocalDateTime createTime = record.getCreateTime();
            long daysBetween = ChronoUnit.DAYS.between(createTime.toLocalDate(), now.toLocalDate());

            // 构造数据
            ChatRecordsVO.item voRecord = ChatRecordsVO.item.builder()
                    .id(record.getId())
                    .userId(record.getUserId())
                    .content(record.getContent())
                    .title(record.getTitle())
                    .createTime(createTime)
                    .build();

            // 分类加入数组
            if (daysBetween == 0) {
                todayRecords.add(voRecord);
            } else if (daysBetween == 1) {
                yesterdayRecords.add(voRecord);
            } else if (daysBetween <= 7) {
                last7DaysRecords.add(voRecord);
            } else if (daysBetween <= 30) {
                lastMonthRecords.add(voRecord);
            } else {
                String key = (createTime.getYear() == now.getYear())
                        ? createTime.getMonth().toString()
                        : createTime.getYear() + "-" + createTime.getMonth().toString();
                olderRecords.computeIfAbsent(key, k -> new ArrayList<>()).add(voRecord);
            }
        }

        // 创键返回数据
        List<ChatRecordsVO> chatRecordsVOS = new ArrayList<>();

        // 将分类结果放入 VO 中
        if (!todayRecords.isEmpty()) {
            chatRecordsVOS.add(ChatRecordsVO.builder().date("今天").records(todayRecords).build());
        }
        if (!yesterdayRecords.isEmpty()) {
            chatRecordsVOS.add(ChatRecordsVO.builder().date("昨天").records(yesterdayRecords).build());
        }
        if (!last7DaysRecords.isEmpty()) {
            chatRecordsVOS.add(ChatRecordsVO.builder().date("7天内").records(last7DaysRecords).build());
        }
        if (!lastMonthRecords.isEmpty()) {
            chatRecordsVOS.add(ChatRecordsVO.builder().date("一月内").records(lastMonthRecords).build());
        }
        if (!olderRecords.isEmpty()) {
            // 遍历 olderRecords，将其转换为 ChatRecordsVO
            olderRecords.forEach((key, items) -> {
                chatRecordsVOS.add(ChatRecordsVO.builder()
                        .date(key) // 使用 Map 的键作为日期描述
                        .records(items) // 添加记录列表
                        .build());
            });
        }

        return chatRecordsVOS;
    }

    /**
     * 根据ID获取聊天记录数据
     * @param recordId
     * @return
     */
    @Override
    public ChatRecordsVO.item queryChatRecordById(Long recordId) {
        return aiMapper.selectById(recordId);
    }

    /**
     * 更新聊天记录数据
     * @param record
     */
    @Override
    public void updateChatRecord(ChatRecordsVO.item record) {
        ChatRecords records = new ChatRecords();
        BeanUtils.copyProperties(record, records);
        records.setUpdateTime(LocalDateTime.now());

        aiMapper.updateById(records);
    }

    /**
     * 删除单个聊天记录
     * @param recordId
     */
    @Override
    public void deleteChatRecord(Long recordId) {
        aiMapper.deleteById(recordId);
    }

}
